/**
 * Copyright (C) 2012 The SkyTvOS Project
 * <p/>
 * Version     Date           Author
 * ─────────────────────────────────────
 * 2014年12月24日         Root.Lu
 */

package com.coocaa.x.framework.utils;

import android.app.Activity;
import android.app.ActivityManager;
import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;

import com.coocaa.x.framework.app.CoocaaApplication;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class Android {
    /**
     * 将px值转换为dip或dp值，保证尺寸大小不变
     *
     * @param pxValue
     * @param scale   （DisplayMetrics类中属性density）
     * @return
     */
    public static int px2dip(float pxValue) {
        DisplayMetrics dm = new DisplayMetrics();
        dm.setToDefaults();
        return (int) (pxValue / dm.density + 0.5f);
    }

    /**
     * 将dip或dp值转换为px值，保证尺寸大小不变
     *
     * @param dipValue
     * @param scale    （DisplayMetrics类中属性density）
     * @return
     */
    public static int dip2px(float dipValue) {
        DisplayMetrics dm = new DisplayMetrics();
        dm.setToDefaults();
        return (int) (dipValue * dm.density + 0.5f);
    }

    /**
     * 将px值转换为sp值，保证文字大小不变
     *
     * @param pxValue
     * @param fontScale （DisplayMetrics类中属性scaledDensity）
     * @return
     */
    public static int px2sp(float pxValue) {
        DisplayMetrics dm = new DisplayMetrics();
        dm.setToDefaults();
        return (int) (pxValue / dm.scaledDensity + 0.5f);
    }

    /**
     * 将sp值转换为px值，保证文字大小不变
     *
     * @param spValue
     * @param fontScale （DisplayMetrics类中属性scaledDensity）
     * @return
     */
    public static int sp2px(float spValue) {
        DisplayMetrics dm = new DisplayMetrics();
        dm.setToDefaults();
        return (int) (spValue * dm.scaledDensity + 0.5f);
    }

    public synchronized static Object getMetaData(Context context, String packageName, String key) {
        ApplicationInfo applicationInfo = null;
        try {
            applicationInfo = context.getPackageManager().getApplicationInfo(packageName,
                    PackageManager.GET_META_DATA);
            if (applicationInfo != null) {
                Object value = null;
                if (applicationInfo.metaData != null) {
                    value = applicationInfo.metaData.get(key);
                }
                if (value == null) {
                    return null;
                }
                return value;
            }
        } catch (NameNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    public static List<ComponentName> getComponentNames(Context context, String action) {
        List<ComponentName> ret = new ArrayList<ComponentName>();
        PackageManager pm = context.getPackageManager();
        Intent intent = new Intent(action);
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 0);
        for (ResolveInfo i : list)
            ret.add(new ComponentName(i.activityInfo.packageName, i.activityInfo.name));

        list = pm.queryBroadcastReceivers(intent, PackageManager.GET_DISABLED_COMPONENTS);
        for (ResolveInfo i : list)
            ret.add(new ComponentName(i.activityInfo.packageName, i.activityInfo.name));
        Collections.sort(ret, new Comparator<ComponentName>() {
            public int compare(ComponentName arg0, ComponentName arg1) {

                return arg0.getPackageName().compareTo(arg1.getPackageName());
            }
        });
        return ret;
    }

    public static List<ComponentName> getCOMPLETEDComponentNamesByPkg(Context context, String pkg) {
        List<ComponentName> ret = new ArrayList<ComponentName>();
        PackageManager pm = context.getPackageManager();
        Intent intent = new Intent(Intent.ACTION_BOOT_COMPLETED);
        intent.setPackage(pkg);
        List<ResolveInfo> list = pm.queryBroadcastReceivers(intent, 0);
        if (list != null && list.size() > 0) {
            for (ResolveInfo i : list) {
                LogUtils.d("completed", "getCOMPLETEDComponentNamesByPkg    pkg:" + i.activityInfo.packageName + " activity:" + i.activityInfo.name);
                ret.add(new ComponentName(i.activityInfo.packageName, i.activityInfo.name));
            }
        }
        return ret;
    }

    public static boolean setComponentEnabledSetting(Context context, ComponentName comptName,
                                                     int state) {
        try {
            PackageManager pm = context.getPackageManager();
            pm.setComponentEnabledSetting(comptName, state, PackageManager.DONT_KILL_APP);//PackageManager.DONT_KILL_APP);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static int getComponentEnabledSetting(Context context, ComponentName comptName) {
        try {
            PackageManager pm = context.getPackageManager();
            return pm.getComponentEnabledSetting(comptName);
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    public static long getVersionCode(Context context, String pkg) {
        PackageManager mPackageManager = context.getApplicationContext().getPackageManager();
        try {
            return mPackageManager.getPackageInfo(pkg, 0).versionCode;
        } catch (Exception e) {
            return -1;
        }
    }

    public static String getVersionName(Context context, String pkg) {
        PackageManager mPackageManager = context.getApplicationContext().getPackageManager();
        try {
            return mPackageManager.getPackageInfo(pkg, 0).versionName;
        } catch (Exception e) {
            return "";
        }
    }

    public static boolean isPackageInstalled(Context context, String pkg) {
        PackageManager mPackageManager = context.getApplicationContext().getPackageManager();
        PackageInfo intent;
        try {
            intent = mPackageManager.getPackageInfo(pkg, 0);
        } catch (NameNotFoundException e) {
            e.printStackTrace();
            return false;
        }
        if (intent == null)
            return false;
        else
            return true;
    }

    public static boolean isNetConnected(Context context) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info != null && info.isAvailable() && info.isConnected()) {
            return true;
        } else
            return false;
    }

    public static void simulateKey(final int KeyCode, final long delay) {
        AsyncTask.runOnThread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(delay);
                    simulateKey(KeyCode);
                } catch (Exception e) {
                    LogUtils.e("Exception when sendKeyDownUpSync", e.toString());
                }
            }
        });
    }

    private static void simulateKey(int KeyCode) {
        Instrumentation inst = new Instrumentation();
        inst.sendKeyDownUpSync(KeyCode);
    }

    public static String throwable2String(Throwable t) {
        String format = "    at %s.%s(%s:%d)\n";
        String msg = t.toString() + "\n";
        StackTraceElement[] es = t.getStackTrace();
        for (StackTraceElement e : es) {
            msg += String.format(format, e.getClassName(), e.getMethodName(), e.getFileName(),
                    e.getLineNumber());
        }
        return msg;
    }

    public static double getBootUptime() {
        String ret = "";
        try {
            BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(
                    "/proc/uptime")));
            String line = reader.readLine();
            String[] results = line.split("\\s+");
            for (int i = 0; i < results.length; i++) {
                if (!results[i].equals("")) {
                    ret = results[i];
                    break;
                }
            }
            reader.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        double uptime = 0d;
        try {
            uptime = Double.parseDouble(ret);
        } catch (Exception e) {
            uptime = 0d;
            e.printStackTrace();
        }
        return uptime;
    }


    public static String getAppNameByPkg(String pkg) {
        String name = "";
        try {
            PackageManager packageManager = CoocaaApplication.getContext().getPackageManager();
            ApplicationInfo applicationInfo = packageManager.getApplicationInfo(pkg, 0);
            name = (String) packageManager.getApplicationLabel(applicationInfo);
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
        }
        return name;
    }

    public static String getNameByActivity(Context context, String packageName, String activityName) {
        try {
            PackageManager pm = context.getPackageManager();
            ActivityInfo ai = pm.getActivityInfo(new ComponentName(packageName,
                    activityName), 0);
            return ai.loadLabel(pm).toString();
        } catch (NameNotFoundException e) {
            e.printStackTrace();
            return getAppNameByPkg(packageName);
        }
    }

    public static Uri getResourceURI(Context context, int resID) {
        String uri = new StringBuilder("res://").append(context.getPackageName()).append("/").append(resID).toString();
        return Uri.parse(uri);
    }

    public static boolean isRunOnMainThread() {
        return Looper.myLooper() == Looper.getMainLooper();
    }

    public static void clearAppData(String packageName) {
        String cmd = "pm clear " + packageName;
        ShellUtils.execCommand(cmd, false);
    }

    public static boolean isAppRunningAtFront(Context c, String pkgname) {
        try {
            ActivityManager am = (ActivityManager) c.getSystemService(Activity.ACTIVITY_SERVICE);
            List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
            ComponentName componentInfo = taskInfo.get(0).topActivity;
            return componentInfo.getPackageName().equals(pkgname);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    public static boolean isInstalledOnSDCard(Context c, String pkg) {
        PackageManager pm = c.getPackageManager();
        try {
            ApplicationInfo info = pm.getApplicationInfo(pkg, PackageManager.GET_DISABLED_COMPONENTS);
//            LogUtils.d("install", " isInstalledOnSDCard:" + info.packageName);
            if ((info.flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0) {
                return true;
            }
        } catch (NameNotFoundException e) {
            e.printStackTrace();
        }
        return false;
    }

    public static class ApkInfo {
        public String apkPath;
        public String appName;
        public String pkgName;
        public String versionName;
        public int versionCode;
    }

    public static ApkInfo getAPKInfo(String apkfile) {
        try {
            ApkInfo info = null;
            PackageInfo packageinfo = CoocaaApplication.getContext().getPackageManager().getPackageArchiveInfo(apkfile,
                    PackageManager.GET_ACTIVITIES);
            if (packageinfo != null) {
                info = new ApkInfo();
                ApplicationInfo appInfo = packageinfo.applicationInfo;
                info.apkPath = apkfile;
                try {
                    info.appName = CoocaaApplication.getContext().getPackageManager().getApplicationLabel(appInfo)
                            .toString();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                info.pkgName = appInfo.packageName;
                info.versionName = packageinfo.versionName;
                info.versionCode = packageinfo.versionCode;
            }
            return info;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    public static String getFileMD5(File file) {
        if (!file.isFile()) {
            return "";
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            in = new FileInputStream(file);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
        BigInteger bigInt = new BigInteger(1, digest.digest());
        String ret = bigInt.toString(16);
        int contact = 32 - ret.length();
        if (contact > 0) {
            StringBuffer s = new StringBuffer();
            for (int i = 0; i < contact; i++)
                s.append("0");
            s.append(ret);
            ret = s.toString();
        }
        return ret;
    }

    public static String getCurrentProcessName(Context context) {
        int pid = android.os.Process.myPid();
        ActivityManager mActivityManager = (ActivityManager) context
                .getSystemService(Context.ACTIVITY_SERVICE);
        for (ActivityManager.RunningAppProcessInfo appProcess : mActivityManager
                .getRunningAppProcesses()) {
            if (appProcess.pid == pid) {
                return appProcess.processName;
            }
        }
        return "";
    }
}
